import path from 'path'
import prompts from 'prompts'
import { red } from 'kolorist'
import ora from 'ora'
import { formatTargetDir, isEmpty, emptyDir } from './utils'
import { frameWorks, FRAMEWORK, VARIANT } from './configs'
import execute from './execute'

interface RESULT {
  projectName: string
  overwrite: boolean
  framework: FRAMEWORK
  variant?: VARIANT['downloadUrl']
}

export default async (targetDir?: string): Promise<void> => {
  const defaultTargetDir = 'chopper-project' // 默认文件名

  let result = {}
  try {
    result = await prompts([
      { // 处理项目名
        type: targetDir !== undefined ? null : 'text', // 如果targetDir存在  则跳过当前命令
        name: 'projectName',
        message: 'Project name:',
        initial: defaultTargetDir,
        onState: (state: { value: string }) => {
          const dir = formatTargetDir(state.value)
          targetDir = dir !== '' ? dir : defaultTargetDir
        }
      },
      { // 文件不为空，重写项目
        type: () =>
          isEmpty(targetDir as string) ? null : 'confirm', // 目标文件 如果存在并且为空跳过
        name: 'overwrite',
        message: () =>
          (targetDir === '.'
            ? 'Current directory'
            : `Target directory "${targetDir as string}"`) +
        ' is not empty. Remove existing files and continue?',
        initial: true
      },
      { // 重写项目为false 退出
        type: (overwrite: boolean) => {
          if (overwrite === false) {
            throw new Error(red('✖') + ' Operation cancelled')
          }
          return null
        },
        name: 'overwriteChecker'
      },
      {
        type: 'select',
        name: 'framework',
        message: 'Select a framework:',
        initial: 0,
        choices: frameWorks.map((framework) => {
          const frameworkColor = framework.color
          return {
            title: frameworkColor(framework.name),
            description: framework.description,
            value: framework
          }
        })
      },
      {
        type: (framework: FRAMEWORK) => (framework.variants === undefined) ? null : 'select',
        name: 'variant',
        message: 'Select a variant:',
        choices: (framework) =>
          (framework.variants as VARIANT[]).map(variant => {
            const variantColor = variant.color
            return {
              title: variantColor(variant.name),
              description: variant.description,
              value: variant.downloadUrl
            }
          })
      }
    ],
    {
      onCancel: () => {
        throw new Error(red('✖') + ' Operation cancelled')
      }
    })
  } catch (error) {
    console.log((error as Error).message)
    return
  }

  const { overwrite, framework, variant } = result as RESULT

  const targetPath: string = path.join(process.cwd(), targetDir as string) // 目标路径

  const downloadUrl = variant !== undefined ? variant : framework.downloadUrl as URL // zip下载路径

  if (overwrite) { // 清空目标文件
    const spinner = ora('Remove existing...').start()
    await emptyDir(targetPath)
    spinner.succeed('Remove existing complete.')
  }
  await execute(targetPath, downloadUrl)
}
